﻿#include "StdAfx.h"
#include "MicrosoftInterface.h"

MicrosoftInterface::MicrosoftInterface(void)
{
	btSocket = INVALID_SOCKET;
}

MicrosoftInterface::~MicrosoftInterface(void)
{
}

// ======================================================================================
/// \brief Implementare Microsoft bazată pe WinSock
// ======================================================================================
RESULT MicrosoftInterface::InitBluetooth()
{
	wVersionRequested = MAKEWORD( 2, 2 );
	if( WSAStartup( wVersionRequested, &wsaData ) == 0 )
	{
		return OK;
	}

	return FAILED;
}
// ======================================================================================
/// \brief Caută echipamente folosind funcţia Microsoft WSALookupService
// ======================================================================================
RESULT MicrosoftInterface::SearchDevices()
{
	BthGetMode(&bluetoothMode);
	if(bluetoothMode == BTH_POWER_OFF)
	{
		BthSetMode(BTH_CONNECTABLE);
	}

	INT				iResult = 0;
	HCURSOR			hCurs;
	HANDLE			hLookup = 0;
	DWORD			dwSize = 0;

	memset (&wsaq, 0, sizeof(wsaq));
	wsaq.dwSize      = sizeof(wsaq);
	wsaq.dwNameSpace = NS_BTH;
	wsaq.lpcsaBuffer = NULL;
	
	// Reset counter
	foundDevicesCount = 0;

	// initialize searching procedure
	iResult = WSALookupServiceBegin(&wsaq, 
		LUP_CONTAINERS, 
		&hLookup);

	if (iResult != 0)
	{
		WSALookupServiceEnd(hLookup);
		return FAILED;
	}

	union {
		CHAR buf[5000];				// returned struct can be quite large 
		SOCKADDR_BTH	__unused;	// properly align buffer to BT_ADDR requirements
	};

	// save the current cursor
	hCurs = GetCursor();
	SetCursor(LoadCursor(NULL, IDC_WAIT));

	for(;;)
	{
		pwsaResults = (LPWSAQUERYSET) buf;
		dwSize  = sizeof(buf);

		memset(pwsaResults,0,sizeof(WSAQUERYSET));
		pwsaResults->dwSize      = sizeof(WSAQUERYSET);
		// namespace MUST be NS_BTH for bluetooth queries
		pwsaResults->dwNameSpace = NS_BTH;
		pwsaResults->lpBlob      = NULL;

		// iterate through all found devices, returning name and address
		// (this sample only uses the name, but address could be used for
		// further queries)
		iResult = WSALookupServiceNext (hLookup, 
			LUP_RETURN_NAME | LUP_RETURN_ADDR, 
			&dwSize, 
			pwsaResults);

		if (iResult != 0)
		{
			iResult = WSAGetLastError();
			if (iResult != WSA_E_NO_MORE)
			{
				WSALookupServiceEnd(hLookup);
				return FAILED;
			}
			// we're finished
			break;
		}

		// Save the name in the device information
		if( pwsaResults->lpszServiceInstanceName)
		{
			wcscpy( Devices[foundDevicesCount].Name, pwsaResults->lpszServiceInstanceName );
		}
		// Save the address
		if( pwsaResults->lpcsaBuffer )
		{
			Devices[foundDevicesCount].Address = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;
		}
		foundDevicesCount++;
	}
	WSALookupServiceEnd(hLookup);
	SetCursor( hCurs );
	return OK;
}
// ======================================================================================
/// \brief Creează un socket penru conexiunea BT
// ======================================================================================
RESULT MicrosoftInterface::Connect(UINT8 index)
{
	// If the socket isn't created
	if( btSocket == INVALID_SOCKET )
	{
		btSocket = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM );
		
		if( btSocket != INVALID_SOCKET )
		{
			memset( &btService, 0, sizeof(btService));
			
			// Set socket to connect on the serial service
			btService.addressFamily = AF_BTH;
			btService.btAddr = Devices[index].Address;
			btService.serviceClassId = SerialPortServiceClass_UUID;

			if( connect( btSocket, (SOCKADDR *) &btService, sizeof(btService) ) != ERROR_SUCCESS)
			{
				Disconnect( index );
				return FAILED;
			}
		} // Socket not created
		else
		{
			Disconnect( index );
			return FAILED;
		}
	}
	Devices[index ].IsPaired = true;
	lastDevice = index;
	return OK;
}
// ======================================================================================
/// \brief Închide socketul
// ======================================================================================
RESULT MicrosoftInterface::Disconnect(UINT8 index)
{
	if( btSocket != INVALID_SOCKET)
	{
		closesocket(btSocket);
		btSocket = INVALID_SOCKET;
	}
	Devices[ index ].IsPaired = false;
	return OK;
}
// ======================================================================================
/// \brief Trimite date utilizând sockets
// ======================================================================================
RESULT MicrosoftInterface::Send(BYTE* data, UINT16 length)
{
	BthGetMode(&bluetoothMode);
	if(bluetoothMode == BTH_POWER_OFF)
	{
		BthSetMode(BTH_CONNECTABLE);
		Disconnect( lastDevice );
		Connect( lastDevice );
	}
	send( btSocket, (char *) data, length, 0 );
	return OK;
}
// ======================================================================================
/// \brief Recepţionează date prin socket
// ======================================================================================
RESULT MicrosoftInterface::Receive(char* data, UINT16 length)
{
	recv( btSocket, data, length, 0 );
	return OK;
}
